<!DOCTYPE html>
<html>
<head>
<title>hello web gl</title>
<script type="text/javascript" src="js/hi.js"></script>
</head>
<body onload="main()">
<div>
<canvas id="canvas" width="400px" height="400px"></canvas>
<script type="text/javascript">


	function main() {
	    //顶点着色器程序
	    let VSHADER_SOURCE =
	        "attribute vec4 a_Position;" +
	        "attribute vec2 a_TextCoord;" + // 接受纹理坐标
	        "varying vec2 v_TexCoord;" +    // 传递纹理坐标
	        "void main() {" +
	        //设置坐标
	        "gl_Position =  a_Position; " +
	        "v_TexCoord = a_TextCoord; " +  // 设置纹理坐标
	        "} ";
	
	    //片元着色器
	    let FSHADER_SOURCE =
	        "precision mediump float;" +  //需要声明浮点数精度，否则报错No precision specified for (float)
	        "uniform sampler2D u_Sampler;" + // 取样器
	        "varying vec2 v_TexCoord;" +  // 接受纹理坐标
	        "void main() {" +
	        //设置颜色
	        "gl_FragColor = texture2D(u_Sampler, v_TexCoord);" +  // 设置颜色
	        "}";
	    //获取canvas元素
	    var canvas = document.getElementById('canvas');
	    //获取绘制二维上下文
	    let gl = canvas.getContext('webgl');
	    //编译着色器
	    let vertShader = gl.createShader(gl.VERTEX_SHADER);
	    gl.shaderSource(vertShader, VSHADER_SOURCE);
	    gl.compileShader(vertShader);
	    let fragShader = gl.createShader(gl.FRAGMENT_SHADER);
	    gl.shaderSource(fragShader, FSHADER_SOURCE);
	    gl.compileShader(fragShader);
	    //合并程序
	    let shaderProgram = gl.createProgram();
	    gl.attachShader(shaderProgram, vertShader);
	    gl.attachShader(shaderProgram, fragShader);
	    gl.linkProgram(shaderProgram);
	    //不加"precision mediump float;" ，则useProgram函数调用会出错。
	    gl.useProgram(shaderProgram);
	    //获取坐标点
	    let a_Position = gl.getAttribLocation(shaderProgram, 'a_Position');
		gl.clearColor(0.0, 0.0, 0.0, 1.0);
		gl.clear(gl.COLOR_BUFFER_BIT);
		initTexture(gl, shaderProgram);
		var tick = function(){
			//绘制一个点
			initBuffers(gl, shaderProgram, 4);
			gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
			animation = requestAnimationFrame(tick);
		}
		tick()
	}

	function initBuffers(gl, shaderProgram) {
		var num = Math.random()*2 - 1;
	    //顶点坐标和纹理坐标
	    var vertices = new Float32Array([
	        -1, 1, 0, num,
	        -1, -1, 0.0, 0.0,
	        1, 1, num, 1.0,
	        1, -1, num, 0.0
	    ]);
	
	    //获取单个字节
	    let FSIZE = vertices.BYTES_PER_ELEMENT;
	    //创建缓冲区对象
	    let vertexBuffer = gl.createBuffer();
	    //将缓冲区对象绑定到目标
	    gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
	    //向缓冲区写入数据
	    gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
	    //获取坐标点
	    let a_Position = gl.getAttribLocation(shaderProgram, 'a_Position');
	    //将缓冲区对象分配给a_Position变量
	    gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, FSIZE * 4, 0);
	    //连接a_Position变量与分配给它的缓冲区对象
	    gl.enableVertexAttribArray(a_Position);
	    //获取纹理坐标点
	    let a_TextCoord = gl.getAttribLocation(shaderProgram, 'a_TextCoord');
	    gl.vertexAttribPointer(a_TextCoord, 2, gl.FLOAT, false, FSIZE * 4, FSIZE * 2);
	    //连接a_TextCoord变量与分配给它的缓冲区对象
	    gl.enableVertexAttribArray(a_TextCoord);
	}
	
	function initTexture(gl, shaderProgram, n) {
	    const texture = gl.createTexture();
	    gl.bindTexture(gl.TEXTURE_2D, texture);
	    const level = 0;
	    const internalFormat = gl.RGBA;
	    const width = 1;
	    const height = 1;
	    const border = 0;	
	    const srcFormat = gl.RGBA;
	    const srcType = gl.UNSIGNED_BYTE;
	    const pixel = new Uint8Array([0, 0, 255, 255]);  // opaque blue
	    gl.texImage2D(gl.TEXTURE_2D, level, internalFormat,
	        width, height, border, srcFormat, srcType,
	        pixel);
	   //创建image对象
	    var image = new Image();
	    //加载纹理
	    image.onload = function(){ loadTexture(gl, texture, image, shaderProgram); };
	    // 浏览器开始加载图片 注意：一定是2^mx2^n尺寸的图片
	    image.src = "./TexturedQuad/ball.jpg";
	}
	
	function loadTexture(gl, texture, image, shaderProgram) {
	    const level = 0;
	    const internalFormat = gl.RGBA;
	    const srcFormat = gl.RGBA;
	    const srcType = gl.UNSIGNED_BYTE;
	    //gl.activeTexture(gl.TEXTURE0);
	    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);
	    gl.bindTexture(gl.TEXTURE_2D, texture);
	    gl.texImage2D(gl.TEXTURE_2D, level, internalFormat,
	        srcFormat, srcType, image);
	    if (isPowerOf2(image.width) && isPowerOf2(image.height)) {
	        gl.generateMipmap(gl.TEXTURE_2D);
	    } else {
	        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
	        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
	        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
	    }
	    var u_Sampler = gl.getUniformLocation(shaderProgram, 'u_Sampler');
	    //6.将0号纹理图像传递给着色器
	    gl.uniform1i(u_Sampler, 0);
	    // 清空 <canvas>
	    gl.clear(gl.COLOR_BUFFER_BIT);
	    //must write the following code, because this function is called when image is loaded successful.
	    gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
	
	}
	
	function isPowerOf2(value) {
	    return (value & (value - 1)) == 0;
	}
</script>
</div>
</body>
</html>